package com.zhihuishu.micro.course.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

import com.github.abel533.mapper.Mapper;
import com.google.common.collect.Sets;
import com.zhihuishu.micro.course.dao.LessonMapper;
import com.zhihuishu.micro.course.dto.LessonDto;
import com.zhihuishu.micro.course.model.Chapter;
import com.zhihuishu.micro.course.model.CourseVideoForBatis;
import com.zhihuishu.micro.course.model.Lesson;
import com.zhihuishu.micro.course.service.ChapterService;
import com.zhihuishu.micro.course.service.CourseBuildService;
import com.zhihuishu.micro.course.service.CourseService;
import com.zhihuishu.micro.course.service.LessonService;
import com.zhihuishu.toolkit.helper.BeanHelper;
import com.zhihuishu.toolkit.jedis.JedisHelper;
import com.zhihuishu.toolkit.jedis.JedisHelper.Handler;

@Service("lessonService")
public class LessonServiceImpl extends BaseServiceImpl<Lesson> implements LessonService {

    @Resource
    private CourseService courseService;

    @Resource
    private ChapterService chapterService;

    @Resource
    private CourseBuildService courseBuildService;

    @Resource
    private LessonMapper lessonMapper;

    @Override
    public LessonDto get(Integer lessonId) {
        if (lessonId == null)
            return null;
        List<LessonDto> list = list(Arrays.asList(lessonId));
        return CollectionUtils.isEmpty(list) ? null : list.get(0);
    }

    private LessonDto toDto(Lesson model) {
        if (model == null)
            return null;
        LessonDto dto = new LessonDto();
        dto.setChapterId(model.getChapterId());
        dto.setId(model.getId());
        dto.setIntroduction(model.getIntroduction());
        dto.setName(model.getName());
        dto.setRank(model.getOrderNumber());
        dto.setVideoId(model.getVideoId());
        dto.setVideoSec(model.getVideoSec());
        dto.setVideoImg(model.getVideoImg());
        dto.setSpeaker(model.getSpeaker());
        dto.setUpdateTime(model.getUpdateTime());
        if (model.getIsHaveChildrenLesson() != null) {
            dto.setHaveChildren(model.getIsHaveChildrenLesson());
        }
        return dto;
    }

    private Lesson toModel(LessonDto lessonDto) {
        if (lessonDto == null) {
            return null;
        }
        Lesson lesson = new Lesson();
        lesson.setChapterId(lessonDto.getChapterId());
        lesson.setCourseId(lessonDto.getCourseId());
        lesson.setId(lessonDto.getId());
        lesson.setIntroduction(lessonDto.getIntroduction());
        lesson.setSpeaker(lessonDto.getSpeaker());
        lesson.setName(lessonDto.getName());
        lesson.setOrderNumber(lessonDto.getRank());
        lesson.setVideoId(lessonDto.getVideoId());
        lesson.setVideoSec(lessonDto.getVideoSec());
        lesson.setVideoImg(lessonDto.getVideoImg());
        lesson.setUpdateTime(lessonDto.getUpdateTime());
        if (lesson.getIsHaveChildrenLesson() != null) {
            lesson.setIsHaveChildrenLesson(lessonDto.getHaveChildren());
        }
        return lesson;

    }

    private LessonDto getFromDb(int lessonId) {
        Lesson model = lessonMapper.get(lessonId);
        if (model == null || model.getId() == null)
            return null;
        return toDto(model);
    }

    @Override
    public void touchLesson(final LessonDto dto) {
        jedisExecutor.execute(new Handler() {

            @Override
            public void handle(Jedis jedis) {
                // 如果查到，转换为哈希结构并写入缓存
                if (dto != null && dto.getId() != null) {
                    // System.out.println(BeanHelper.describe(dto));
                    jedis.del(JedisHelper.key("cc:lesson", dto.getId()));
                    jedis.hmset(JedisHelper.key("cc:lesson", dto.getId()), BeanHelper.describe(dto));

                }

            }
        });

    }

    @Override
    public LessonDto touchLesson(final int lessonId) {
        final LessonDto target = new LessonDto();
        jedisExecutor.execute(new Handler() {
            @Override
            public void handle(Jedis jedis) {
                // 数据库查询章
                LessonDto dto = getFromDb(lessonId);
                // 如果查到，转换为哈希结构并写入缓存
                if (dto != null && dto.getId() != null) {
                    // System.out.println(BeanHelper.describe(dto));
                    jedis.del(JedisHelper.key("cc:lesson", lessonId));
                    jedis.hmset(JedisHelper.key("cc:lesson", lessonId), BeanHelper.describe(dto));
                    BeanHelper.copyProperties(dto, target);
                }
            }
        });
        return target.getId() != null ? target : null;
    }

    @Override
    public void addLessonOnCourseRedis(final long courseId, final int lessonId) {
        jedisExecutor.execute(new Handler() {
            @Override
            public void handle(Jedis jedis) {
                // System.out.println(JedisHelper.key("cc:course" ,courseId
                // ,"lessons")+"---"+lessonId);
                jedis.sadd(JedisHelper.key("cc:course", courseId, "lessons"), String.valueOf(lessonId));
            }
        });
        courseService.updateCourseVideoTotalRedis(courseId);
    }

    @Override
    public void removeLessonOnCourseRedis(final long courseId, final int lessonId) {
        jedisExecutor.execute(new Handler() {
            @Override
            public void handle(Jedis jedis) {
                jedis.srem(JedisHelper.key("cc:course", courseId, "lessons"), String.valueOf(lessonId));
            }
        });
        courseService.updateCourseVideoTotalRedis(courseId);
    }

    @Override
    public int countVideos(List<Integer> chapterIds) {
        return lessonMapper.countVideos(chapterIds);
    }

    @Override
    public List<LessonDto> list(int chapterId) {
        List<Integer> lessonIds = lessonMapper.list(chapterId);
        if (CollectionUtils.isEmpty(lessonIds))
            return null;
        return this.list(lessonIds);
    }

    @Override
    public List<LessonDto> list(final List<Integer> lessonIds) {
        if (CollectionUtils.isEmpty(lessonIds))
            return null;
        final List<LessonDto> list = new ArrayList<LessonDto>();
        jedisExecutor.execute(new Handler() {
            @Override
            public void handle(Jedis jedis) {
                for (Integer lessonId : lessonIds) {
                    if (lessonId == null)
                        continue;
                    // 根据主键从Redis中获取数据
                    LessonDto dto = null;
                    Map<String, String> hash = jedis.hgetAll(JedisHelper.key("cc:lesson", lessonId));
                    if (CollectionUtils.isEmpty(hash)) {
                        dto = touchLesson(lessonId);
                    } else {
                        dto = BeanHelper.transTo(hash, LessonDto.class);
                    }
                    if (dto != null)
                        list.add(dto);
                }
            }
        });
        return list.isEmpty() ? null : list;
    }

    @Override
    public List<CourseVideoForBatis> getLessonByCourseIds(List<Long> courseIds) {
        return lessonMapper.getLessonByCourseIds(courseIds);
    }

    @Override
    public List<LessonDto> getLessonListFromDb(Integer chapterId) {
        List<LessonDto> resultList = null;
        List<Lesson> lessonList = lessonMapper.getLessonListFromDb(chapterId);
        if (lessonList != null && lessonList.size() > 0) {
            resultList = new ArrayList<LessonDto>();
            for (Lesson lesson : lessonList) {
                LessonDto lessonDto = new LessonDto();
                lessonDto = toDto(lesson);
                resultList.add(lessonDto);
            }
        }
        return resultList;

    }

    @Override
    public Mapper<Lesson> getMapper() {
        // TODO Auto-generated method stub
        return lessonMapper;
    }

    @Override
    public void saveLessonForApp(LessonDto lessonDto, Long userId) {
        lessonDto.setHaveChildren(0);// 默认没有子小节
        int maxSort = lessonMapper.queryMaxLessonSortOfChapter(lessonDto.getChapterId());
        if (logger.isDebugEnabled()) {
            logger.debug("查询到章{}下节最大的序号为{}", lessonDto.getChapterId(), maxSort);
        }
        lessonDto.setRank(maxSort + 1);
        Lesson lesson = toModel(lessonDto);
        lessonMapper.insertSelective(lesson);
        lessonDto.setId(lesson.getId());

        // 添加节 修改节所在的章为未通过
        Chapter chapter = new Chapter();
        chapter.setId(lessonDto.getChapterId());
        chapter.setUpdateTime(new Date());
        chapter.setIsPass(0);
        chapterService.updateSelective(chapter);
        touchLesson(lessonDto);// 保存到缓存中
        // 添加节 更新第三步为不完整
        courseBuildService.updateCourseStepStat(lessonDto.getCourseId(), 3, 0);

    }

    @Override
    public List<Integer> queryLessonsByChapterIdAndOrderNumber(Integer chapterId, Integer orderNumber) {
        List<Integer> lessonIds = lessonMapper.queryLessonsByChapterIdAndOrderNumber(chapterId, orderNumber);
        return lessonIds;
    }

    @Override
    public void updateMinusOrderByChapterIdAndLessonOrderNumber(Integer chapterId, Integer orderNumber) {
        lessonMapper.updateMinusOrderByChapterIdAndLessonOrderNumber(chapterId, orderNumber);

    }

    @Override
    public List<Integer> queryLessonIdsContainSmallOrder(Integer chapterId, int targetRankSmall,
            int orginRankBig) {
        List<Integer> lessonIds = lessonMapper.queryLessonIdsContainSmallOrder(chapterId, targetRankSmall,
                orginRankBig);
        if (lessonIds != null && lessonIds.size() > 0) {
            lessonMapper.updatePlusLessonOrderContainSmallOrder(chapterId, targetRankSmall, orginRankBig);
        }
        return lessonIds;
    }

    @Override
    public List<Integer> queryLessonIdsContainBigOrder(Integer chapterId, int targetRankBig,
            int orginRankSmall) {
        List<Integer> lessonIds = lessonMapper.queryLessonIdsContainsBigOrder(chapterId, targetRankBig,
                orginRankSmall);
        if (lessonIds != null && lessonIds.size() > 0) {
            lessonMapper.updateMinusLessonOrderContainBigOrder(chapterId, targetRankBig, orginRankSmall);
        }
        return lessonIds;
    }

    @Override
    public void updateLessonVideoInfoAndChildCount(Integer lessonId, int lessonVideoCount) {
        lessonMapper.updateLessonVideoInfoAndChildCount(lessonId, lessonVideoCount);
    }

    @Override
    public void updateChildCount(Integer count, Integer lessonId) {
        Lesson lesson = new Lesson();
        lesson.setId(lessonId);
        lesson.setIsHaveChildrenLesson(count);
        lesson.setUpdateTime(new Date());
        lessonMapper.updateByPrimaryKeySelective(lesson);

    }

    @Override
    public void updatLessonKnowLedgeFlag(Integer lessonId, int i) {
        Lesson lesson = new Lesson();
        lesson.setId(lessonId);
        lesson.setHasKnowledegPoint(i);
        lesson.setUpdateTime(new Date());
        lessonMapper.updateByPrimaryKeySelective(lesson);

    }

    @Override
    public Set<String> queryLessonIdsByCourseId(final long courseId) {
        List<Integer> lessonIds = lessonMapper.queryLessonIdsByCourseId(courseId);
        if (logger.isDebugEnabled()) {
            logger.debug("查询到的节ids为{}", lessonIds);
        }
        if (CollectionUtils.isEmpty(lessonIds)) {
            return Sets.newHashSetWithExpectedSize(0);
        }
        addLessonIdsToCache(courseId, lessonIds);// 添加ids到缓存
        addlessonInfoToCache(lessonIds);// 节详细信息存放到缓存
        Set<String> set = Sets.newHashSetWithExpectedSize(lessonIds.size());
        for (Integer temp : lessonIds) {
            set.add(temp.toString());
        }
        return set;
    }

    private void addlessonInfoToCache(List<Integer> lessonIds) {
        if (CollectionUtils.isEmpty(lessonIds)) {
            return;
        }
        final List<Lesson> list = lessonMapper.getList(lessonIds);
        if (logger.isDebugEnabled()) {
            logger.debug("查询到节的属性信息为{}", list);
        }
        jedisExecutor.execute(new Handler() {
            @Override
            public void handle(Jedis jedis) {
                Pipeline pipelined = jedis.pipelined();
                String key;
                Map<String, String> hash;
                for (Lesson lesson : list) {
                    key = JedisHelper.key("cc:lesson", lesson.getId());
                    hash = BeanHelper.describe(toDto(lesson));

                    pipelined.hmset(key, hash);
                }
                pipelined.sync();

            }
        });

    }

    private void addLessonIdsToCache(final long courseId, List<Integer> lessonIds) {
        if (CollectionUtils.isEmpty(lessonIds)) {
            return;
        }
        final String[] lessonIdArr = new String[lessonIds.size()];
        for (int i = 0; i < lessonIds.size(); i++) {
            lessonIdArr[i] = lessonIds.get(i).toString();
        }
        jedisExecutor.execute(new Handler() {

            @Override
            public void handle(Jedis jedis) {
                String key = JedisHelper.key("cc:course", courseId, "lessons");
                jedis.sadd(key, lessonIdArr);

            }
        });
    }

    @Override
    public List<Integer> getlessonIdsByCourseId(long courseId) {

        return lessonMapper.getlessonIdsByCourseId(courseId);
    }

}
